#include "battery.h"
#include <avr/io.h>
#include <avr/interrupt.h>

#define BATT_PORT PORTD
#define BATT_DDR DDRD
/**
 * @brief Pin where the battery voltage will be readed.
 */
#define BATT_PIN PD7

//ADC value when ADC0 reaches 2,6 V (battery power = 5,2 V)
#define ADC_BATT_100 150

#if NXBOT_USE_12VBATT==1
//Value of ADC when battState should report 0%
#define ADC_BATT_0 64 
//Value of ADC when Batt. Led should be RED (No battery).
#define ADC_BATT_LIMIT 69
//Values of ADC higher than this should report 100% in battState
#define BATT_VOLT_MAX 1200
#define BATT_VOLT_MIN 1000
#else
//Value of ADC when battState should report 0%
#define ADC_BATT_0 134
//Value of ADC when Batt. Led should be RED (No battery).
#define ADC_BATT_LIMIT 142
#define BATT_VOLT_MAX 600
#define BATT_VOLT_MIN 500
#endif

#define BATT_LINEALIZE 4



//variable that reports amount of power, from 0% to 100%
static unsigned char battState;
//variable that reports amount of power, in volts. From 0 to 600 (assuming 6V battery) or 0 to 1200 (assuming 12V battery)
static unsigned int battVoltage;


void battery_init()
{
	BATT_DDR |= (1<<BATT_PIN);
	
	//Configuration of ADC
	//Resolution of 8 bits (ADLAR, left Adjust), AVCC reference.	
	ADMUX |= (1<<REFS0) | (1<<ADLAR);
	//Enable ADC, Start conversion, Auto trigger enable, Interrupt enable.
	ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
	//Disable digital input from ADC0 channel. This will reduce consumption power.
	DIDR0 |= (1<<ADC0D);
}


void battery_ledEnable(unsigned char en)
{
	if(en)
		BATT_PORT |= (1<<BATT_PIN);
	else
		BATT_PORT &= ~(1<<BATT_PIN);
}

unsigned char battery_getState()
{
	return battState;
}


unsigned int battery_getVoltage()
{
	return battVoltage;
}

unsigned int battery_read(unsigned char type)
{
	if(type == BATT_READ_VOLT)
		return battVoltage;
	else
		return battState;
		
}

ISR(ADC_vect)
{
	//battery voltage = ADCH * 4. BATT_LINEALIZE
	#if NXBOT_USE_12VBATT==1
	battVoltage = ((ADCH - BATT_LINEALIZE)<<3);	
	#else
	battVoltage = ((ADCH - BATT_LINEALIZE)<<2);	
	#endif	
	
	//when battery is full
	if(ADCH>ADC_BATT_100)
		battState = 100;
	//when battery is empty
	else if(ADCH<ADC_BATT_0)
		battState = 0;
	else
		#if NXBOT_USE_12VBATT==1
		battState = (char)((battVoltage>>2)-BATT_VOLT_MIN);			
		#else
		battState = (char)(battVoltage-BATT_VOLT_MIN);	
		#endif

	//inform battery state to user
	if(ADCH<=ADC_BATT_LIMIT)
		battery_ledEnable(OFF);
	else
		battery_ledEnable(ON);
	
}
